package com.ticket.system.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson2.JSON;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.common.collect.Maps;
import com.ticket.common.constant.CacheConstants;
import com.ticket.common.constant.PerformConstants;
import com.ticket.common.core.domain.AjaxResult;
import com.ticket.common.core.domain.entity.SysUser;
import com.ticket.common.core.domain.model.LoginUser;
import com.ticket.common.core.redis.RedisCache;
import com.ticket.common.exception.ServiceException;
import com.ticket.common.utils.Const;
import com.ticket.common.utils.DateUtils;
import com.ticket.common.utils.SecurityUtils;
import com.ticket.common.utils.StringUtils;
import com.ticket.common.utils.ip.IpUtils;
import com.ticket.system.domain.*;
import com.ticket.system.domain.enu.OrderStatusEnum;
import com.ticket.system.domain.enu.TicketStatusEnum;
import com.ticket.system.domain.vo.*;
import com.ticket.system.mapper.*;
import com.ticket.system.service.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 订单Service业务层处理
 *
 * @author ruoyi
 * @date 2023-09-26
 */
@Service
public class YanchuOrderServiceImpl implements IYanchuOrderService {
    private static final Logger logger = LoggerFactory.getLogger(YanchuOrderServiceImpl.class);
    @Autowired
    private YanchuOrderMapper yanchuOrderMapper;
    @Autowired
    private YanchuSeatMapper yanchuSeatMapper;

    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private YanchuOrderDetailMapper yanchuOrderDetailMapper;

    @Autowired
    private IYanchuSeatService iYanchuSeatService;

    @Autowired
    private IYanchuScoreService iYanchuScoreService;
    @Autowired
    private WxPayService wxService;

    @Autowired
    private IYanchuOrderDetailService iYanchuOrderDetailService;
    @Autowired
    private YanchuSessionMapper yanchuSessionMapper;
    @Autowired
    private YanchuUserInfoMapper yanchuUserInfoMapper;

    @Autowired
    private IYanchuTicketPriceService iYanchuTicketPriceService;

    @Value("${notifyUrl}")
    private String notifyUrl;
    @Value("${tempUrl}")
    private String tempUrl;

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private IYanchuMovieCardService yanchuMovieCardService;

    @Autowired
    private IYanchuStorageCradService yanchuStorageCradService;

    @Autowired
    private YanchuConsumeRecordMapper yanchuConsumeRecordMapper;

    /**
     * 查询订单
     *
     * @param id 订单主键
     * @return 订单
     */
    @Override
    public OrderVo selectYanchuOrderById(Long id) {
        OrderVo orderVo = yanchuOrderMapper.selectOrderVoById(id);
        if (null != orderVo) {
            orderVo.getSessionVo().setWeek(DateUtils.dateToWeek(orderVo.getSessionVo().getSessionDate()));
            List<OrderDetailVo> orderDetailVoList = yanchuOrderDetailMapper.selectOrderDetailByOrderId(id);
            orderVo.setOrderDetailVos(orderDetailVoList);
        }
        return orderVo;
    }

    @Override
    public DetailInfoVO getDetailInfo(String orderId) {

        return yanchuOrderMapper.getDetailInfo(orderId);
    }

    @Override
    public TicketInfoVO getTicketDetail(String orderId) {
        return yanchuOrderMapper.getTicketDetail(orderId);
    }

    @Override
    public YanchuOrder selectOrderById(Long id) {
        logger.debug("selectOrderById id:{}", id);
        return yanchuOrderMapper.selectYanchuOrderById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public YanchuOrder selectOrderPayByOrderNo(String orderNo) throws WxPayException {
        logger.debug("selectOrderPayByOrderNo orderNo:{}", orderNo);
        YanchuOrder order = yanchuOrderMapper.selectYanchuOrderByNo(orderNo);
        if (null == order) {
            return null;
        }

        //未支付补偿查询后更新
        if (order.getStatus() != PerformConstants.ORDER_PAY &&
                order.getStatus() != PerformConstants.ORDER_WAIT_REFUND) {
            WxPayOrderQueryResult result = wxService.queryOrder(null, orderNo);
            logger.info("WxPayOrderQueryResult:{}",result);
            if (WxPayConstants.WxpayTradeStatus.SUCCESS.equals(result.getReturnCode()) &&
                    WxPayConstants.WxpayTradeStatus.SUCCESS.equals(result.getTradeState()) &&
                    WxPayConstants.WxpayTradeStatus.SUCCESS.equals(result.getResultCode())) {//已支付补偿
                String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
                notifyOrder(orderNo, new BigDecimal(totalFee), result.getTransactionId(),order);
            }
        }
        return order;
    }

    @Override
    public OrderVo selectOrderVoById(Long id) {
        OrderVo orderVo = yanchuOrderMapper.selectOrderVoById(id);
        if (null != orderVo) {
            //获取场次日期星期
            String week = DateUtils.dateToWeek(orderVo.getSessionVo().getSessionDate());
            orderVo.getSessionVo().setWeek(week);

            //查询订单详情信息
            List<OrderDetailVo> orderDetailVoList = iYanchuOrderDetailService.selectOrderDetailByOrderId(id);
            orderVo.setOrderDetailVos(orderDetailVoList);
        }
        return orderVo;
    }

    /**
     * 查询订单列表
     *
     * @param yanchuOrder 订单
     * @return 订单
     */
    @Override
    public List<YanchuOrder> selectYanchuOrderList(YanchuOrder yanchuOrder) {
        return yanchuOrderMapper.selectYanchuOrderList(yanchuOrder);
    }

    @Override
    public List<YanchuOrderVO> selectOrderList(QueryOrderListVO query) {
        List<YanchuOrderVO> yanchuOrderVOS = yanchuOrderMapper.selectOrderList(query);
        if (CollectionUtils.isEmpty(yanchuOrderVOS)){
            return Collections.EMPTY_LIST;
        }
        String num = null;
        for (YanchuOrderVO yanchuOrderVO : yanchuOrderVOS) {
            num = StringUtils.isEmpty(yanchuOrderVO.getNum())?"0.00":yanchuOrderVO.getNum();
            List<String> list = Arrays.asList(num.split(","));
            Map<String, Long> collect = list.stream().collect(Collectors.groupingBy(k -> k, Collectors.counting()));
            Map<BigDecimal, Integer> map = new HashMap<>();
            //定义原价
            BigDecimal titlePrice = new BigDecimal("0.00");
            //TODO:定义减免(具体算法在下期)
            BigDecimal promotionPrice = new BigDecimal("0.00");
            //定义应收价格
            for (String s : collect.keySet()) {
                //计算原价
                titlePrice = (new BigDecimal(s).multiply(BigDecimal.valueOf(collect.get(s)))).add(titlePrice);
                map.put(new BigDecimal(s),collect.get(s).intValue());
            }
            Map<String, BigDecimal>  map1 = new HashMap<>();
            map1.put("titlePrice",titlePrice);
            map1.put("promotionPrice",promotionPrice);
            map1.put("receivablePrice",yanchuOrderVO.getYingfuMoney());
            map1.put("totalMoney",yanchuOrderVO.getTotalMoney());
            yanchuOrderVO.setTicket(map);
            yanchuOrderVO.setPrice(map1);
        }
        return yanchuOrderVOS;
    }

    @Override
    public List<OrderVo> selectUserOrderVoList(YanchuOrder yanchuOrder) {
        return yanchuOrderMapper.selectUserOrderVoList(yanchuOrder);
    }

    /**
     * 新增订单
     *
     * @param orderVo 订单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertYanchuOrder(OrderParamVo orderVo,YanchuSession yanchuSession) throws WxPayException {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(StringUtils.isEmpty(loginUser.getUser().getOpenId())){
            SysUser sysUser = sysUserMapper.selectUserById(loginUser.getUser().getUserId());
            if(null != sysUser && StringUtils.isNotEmpty(sysUser.getOpenId())){
                loginUser.getUser().setOpenId(sysUser.getOpenId());
            }
        }
        orderVo.setTicketType(PerformConstants.TICKET_TYPE_WECHAT);
		YanchuOrder yanchuOrder = insertOrder(orderVo,loginUser,yanchuSession,PerformConstants.ORDER_WAIT_PAY);
        List<YanchuSeat> seatList = iYanchuSeatService.grabTicket(orderVo.getSessionId(), loginUser.getUser().getUserId(),
                orderVo.getSeatVos(), yanchuOrder.getId());
        int count = batchDetail(orderVo.getSeatVos(), yanchuOrder, yanchuOrder.getExpireTime(),seatList,yanchuSession,PerformConstants.ORDER_WAIT_PAY);
        if(CollectionUtils.isNotEmpty(orderVo.getCardVos())){
            int reduceCount = 0;
            for(CardVo cardVo:orderVo.getCardVos()){
                reduceCount = yanchuMovieCardService.consume(yanchuOrder,cardVo);
                if(reduceCount <= 0){
                    throw new ServiceException("更新观演卡余额失败！");
                }
            }
        }
        if(orderVo.getBalanceAmt().compareTo(BigDecimal.ZERO) > 0){
            int balanceCount = yanchuStorageCradService.consume(yanchuOrder);
            if(balanceCount <= 0){
                throw new ServiceException("更新余额失败！");
            }
        }

        WxPayMpOrderResult result = null;
        if (count > 0) {
            result = unifiedOrder(yanchuOrder, loginUser,"/system/order/payNotify/forAllUser","在线购票");
            redisCache.setCacheObject(CacheConstants.ORDER_UNI_KEY+yanchuOrder.getId(),result,2, TimeUnit.HOURS);
            logger.debug("result:{}", JSON.toJSONString(result));
        } else {
            throw new ServiceException("保存订单失败！");
        }

        AjaxResult resultAjax = AjaxResult.success();
        resultAjax.put("result",result);
        resultAjax.put("seatList",seatList);
        resultAjax.put("orderNo",yanchuOrder.getOrderId());
        resultAjax.put("orderId",yanchuOrder.getId());
        return resultAjax;
    }

	@Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertNoPayYanchuOrder(OrderParamVo orderVo,YanchuSession yanchuSession) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(StringUtils.isEmpty(loginUser.getUser().getOpenId())){
            SysUser sysUser = sysUserMapper.selectUserById(loginUser.getUser().getUserId());
            if(null != sysUser && StringUtils.isNotEmpty(sysUser.getOpenId())){
                loginUser.getUser().setOpenId(sysUser.getOpenId());
            }
        }
        orderVo.setTicketType(PerformConstants.TICKET_TYPE_WECHAT);
        YanchuOrder yanchuOrder = insertOrder(orderVo,loginUser,yanchuSession,PerformConstants.ORDER_PAY);
        List<YanchuSeat> seatList = iYanchuSeatService.grabNoPayTicket(orderVo.getSessionId(), loginUser.getUser().getUserId(),
                orderVo.getSeatVos(), yanchuOrder.getId());
        int detailCount = batchDetail(orderVo.getSeatVos(), yanchuOrder, yanchuOrder.getExpireTime(),seatList,yanchuSession,PerformConstants.ORDER_PAY);
        if(CollectionUtils.isNotEmpty(orderVo.getCardVos())){
            int reduceCount = 0;
            for(CardVo cardVo:orderVo.getCardVos()){
                if(StringUtils.isEmpty(cardVo.getCardNum())){
                    throw new ServiceException("卡号不能为空！");
                }
                if(null == cardVo.getAmount() || cardVo.getAmount().compareTo(BigDecimal.ZERO)<=0){
                    throw new ServiceException("观演卡消费金额不正确！");
                }
                reduceCount = yanchuMovieCardService.consume(yanchuOrder,cardVo);
                if(reduceCount <= 0){
                    throw new ServiceException("更新观演卡余额失败！");
                }
            }
        }
        if(null != orderVo.getBalanceAmt() && orderVo.getBalanceAmt().compareTo(BigDecimal.ZERO) > 0){
            int balanceCount = yanchuStorageCradService.consume(yanchuOrder);
            if(balanceCount <= 0){
                throw new ServiceException("更新余额失败！");
            }
        }

        //更新票房、积分
        iYanchuScoreService.updateNumsMoney(detailCount, orderVo.getTotalMoney(), yanchuOrder.getSessionId(),
                yanchuOrder.getUserId(), orderVo.getTotalMoney().intValue(),orderVo.getPerformId(),yanchuOrder);
        AjaxResult resultAjax = AjaxResult.success();
        resultAjax.put("seatList",seatList);
        resultAjax.put("orderNo",yanchuOrder.getOrderId());
        resultAjax.put("orderId",yanchuOrder.getId());
        return resultAjax;
    }

    /**
     * 新增出票
     * @param orderVo
     * @param yanchuSession
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertYanchuBackendOrder(OrderParamVo orderVo, YanchuSession yanchuSession){
        LoginUser loginUser = SecurityUtils.getLoginUser();
        orderVo.setTicketType(PerformConstants.TICKET_TYPE_BACKEND);
        YanchuOrder yanchuOrder = insertOrder(orderVo,loginUser,yanchuSession,PerformConstants.ORDER_PAY);
        AjaxResult resultAjax = iYanchuSeatService.grabBackendTicket(orderVo.getSessionId(), loginUser.getUser().getUserId(),
                orderVo.getSeatVos(), yanchuOrder.getId());
        List<SeatVo> errorList = (List<SeatVo>)resultAjax.get("errorList");

        if(CollectionUtils.isNotEmpty(errorList)){
            StringBuilder sb = new StringBuilder();
            for(SeatVo vo:errorList){
                sb.append(vo.getSeatStr()).append(",持票人：");
                if(StringUtils.isNotEmpty(vo.getUserName())){
                    sb.append(vo.getUserName()).append("/");
                }
                sb.append(StringUtils.isNotEmpty(vo.getBuyerPhone())?vo.getBuyerPhone():"").append(";");
                if(orderVo.getTotalMoney().compareTo(BigDecimal.ZERO)>0){
                    yanchuOrder.setYingfuMoney(orderVo.getYingfuMoney().subtract(orderVo.getYingfuMoney()));
                    yanchuOrder.setDiscountAmt(orderVo.getDiscountAmt().subtract(orderVo.getDiscountAmt()));
                    yanchuOrder.setTotalMoney(orderVo.getTotalMoney().subtract(vo.getMoney()));
                }
            }
            resultAjax.put("listMsg",sb.toString());
            this.updateYanchuOrder(yanchuOrder);
        }
        List<YanchuSeat> seatList = (List<YanchuSeat>)resultAjax.get("seatList");
        if(CollectionUtils.isEmpty(seatList)){
            return resultAjax;
        }

        int detailCount = batchDetail(orderVo.getSeatVos(), yanchuOrder, yanchuOrder.getExpireTime(),seatList,yanchuSession,PerformConstants.ORDER_PAY);
        //更新票房、积分
        iYanchuScoreService.updateNumsMoney(detailCount, yanchuOrder.getTotalMoney(), yanchuOrder.getSessionId(),
                yanchuOrder.getUserId(), yanchuOrder.getTotalMoney().intValue(),orderVo.getPerformId(),yanchuOrder);

        resultAjax.put("orderNo",yanchuOrder.getOrderId());
        resultAjax.put("orderId",yanchuOrder.getId());
        return resultAjax;
    }

	private YanchuOrder insertOrder(OrderParamVo orderVo,LoginUser loginUser,YanchuSession yanchuSession,Integer status){
        logger.info("insertYanchuOrder orderVo:{} wxUser:{}", JSON.toJSONString(orderVo), loginUser.getUser().getUserId());
        String orderNo = DateUtils.dateTimeNow() + orderVo.getPerformId() + yanchuSession.getId() + loginUser.getUser().getUserId() +
                RandomUtil.randomInt(1, 1000);
        Date expireTime = DateUtils.addMinutes(new Date(), 30);//订单最晚支付时间
        YanchuOrder yanchuOrder = new YanchuOrder();
        yanchuOrder.setCreateTime(DateUtils.getNowDate());
        yanchuOrder.setOrderId(orderNo);
        yanchuOrder.setSessionId(orderVo.getSessionId());
        yanchuOrder.setTotalMoney(orderVo.getTotalMoney());
        yanchuOrder.setYanchuStart(yanchuSession.getPlayTime());
        yanchuOrder.setYanchuEnd(yanchuSession.getEndTime());
        yanchuOrder.setExpireTime(expireTime);
        yanchuOrder.setStatus(status);
        yanchuOrder.setOperaId(yanchuSession.getOperaId());
        yanchuOrder.setContacts(orderVo.getContacts());
        yanchuOrder.setContactNumber(orderVo.getContactNumber());
        yanchuOrder.setPerformId(orderVo.getPerformId());
        yanchuOrder.setBalanceAmt(orderVo.getBalanceAmt());
        yanchuOrder.setCardAmt(orderVo.getCardAmt());
        yanchuOrder.setWechatAmt(orderVo.getWechatAmt());
        if(null == orderVo.getYingfuMoney()){
            yanchuOrder.setYingfuMoney(orderVo.getTotalMoney());
        }else{
            yanchuOrder.setYingfuMoney(orderVo.getYingfuMoney());
        }

        yanchuOrder.setTicketType(orderVo.getTicketType());
        yanchuOrder.setUserId(loginUser.getUser().getUserId());
        if(PerformConstants.TICKET_TYPE_BACKEND == orderVo.getTicketType()){
            yanchuOrder.setDiscountAmt(orderVo.getDiscountAmt());
            yanchuOrder.setDiscountType(orderVo.getDiscountType());
            yanchuOrder.setDiscountPer(orderVo.getDiscountPer());
            yanchuOrder.setPayWay(orderVo.getPayWay());
            yanchuOrder.setTicketOutWay(orderVo.getTicketOutWay());
            yanchuOrder.setTicketWay(orderVo.getTicketWay());
            yanchuOrder.setTicketDemo(orderVo.getTicketDemo());
            yanchuOrder.setTicketStatus(orderVo.getTicketStatus());
            yanchuOrder.setPayDemo(orderVo.getPayDemo());
            yanchuOrder.setTicketWayName(orderVo.getTicketWayName());
            yanchuOrder.setPayName(orderVo.getPayName());
        }else{
            yanchuOrder.setOpenId(loginUser.getUser().getOpenId());
        }

        String ip = IpUtils.getIpAddr();
        yanchuOrder.setUserIp(ip);
        yanchuOrderMapper.insertYanchuOrder(yanchuOrder);
        return yanchuOrder;
    }


    /**
     * 下单
     * @param yanchuOrder
     * @param loginUser
     * @return
     * @throws WxPayException
     */
    public WxPayMpOrderResult unifiedOrder(YanchuOrder yanchuOrder, LoginUser loginUser,String notifyPayUrl,String body) throws WxPayException {
        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setBody(body);
        orderRequest.setOutTradeNo(yanchuOrder.getOrderId());
        orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(yanchuOrder.getWechatAmt() + ""));//元转成分
        orderRequest.setOpenid(loginUser.getUser().getOpenId());
        orderRequest.setSpbillCreateIp(yanchuOrder.getUserIp());
        orderRequest.setNotifyUrl(notifyUrl+notifyPayUrl);
        orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
        return wxPayService.createOrder(orderRequest);
    }

    /**
     * 批量保存订单详情
     * @param seatVos
     * @param yanchuOrder
     * @param expireTime
     * @param seatList
     * @param yanchuSession
     * @param status
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int batchDetail(List<SeatVo> seatVos, YanchuOrder yanchuOrder, Date expireTime,List<YanchuSeat> seatList,
                            YanchuSession yanchuSession,Integer status) {
        YanchuOrderDetail yanchuOrderDetail = null;
        List<YanchuOrderDetail> details = Lists.newArrayList();
        SeatVo seat = null;
        Map<String,YanchuSeat> seatMap = Maps.newHashMap();
        YanchuSeat yanchuSeat = null;
        for(YanchuSeat seatDb:seatList){
            seatMap.put(seatDb.getAreaId()+":"+seatDb.getRowNumber()+":"+seatDb.getxPos(),seatDb);
        }
        YanchuUserInfo userInfo = null;
        PriceVo yanchuTicketPrice = null;
        Integer authType = yanchuSession.getAutType();
        List<String> idNums = seatVos.stream().map(s->s.getIdNum()).distinct().collect(Collectors.toList());
        if(authType != PerformConstants.AUTH_NONE && yanchuOrder.getTicketType().equals(PerformConstants.TICKET_TYPE_WECHAT)){
            int count = yanchuOrderDetailMapper.insertBatchCheck(idNums,yanchuOrder.getSessionId());
            if(count > 0){
                throw new ServiceException("当前场次已存在身份证购票信息！");
            }
        }
        List<PriceVo> priceList = iYanchuTicketPriceService.selectTicketPriceVoList(yanchuSession.getId());
        Map<Long, PriceVo> priceMap = priceList.stream().collect(Collectors.toMap(PriceVo::getPriceId, (p) -> p));
        for (int i = 0; i < seatVos.size(); i++) {
            seat = seatVos.get(i);

            yanchuSeat = seatMap.get(seat.getAreaId()+":"+seat.getRowNumber()+":"+seat.getxPos());
            if(null == yanchuSeat){
                continue;
            }
            yanchuOrderDetail = new YanchuOrderDetail();
            yanchuOrderDetail.setOrderId(yanchuOrder.getId());
            yanchuOrderDetail.setAreaId(seat.getAreaId());
            yanchuOrderDetail.setHallId(seat.getHallId());
            yanchuOrderDetail.setRowNumber(seat.getRowNumber());
            yanchuOrderDetail.setSeatNumber(seat.getSeat());
            yanchuOrderDetail.setSessionId(yanchuSession.getId());
            yanchuOrderDetail.setStatus(status);
            yanchuOrderDetail.setxPos(Long.valueOf(seat.getxPos()));
            yanchuOrderDetail.setTab(seat.getTab());
            yanchuOrderDetail.setRowNo(seat.getRowNo());
            if(null != seat.getMoney()){
                yanchuOrderDetail.setMoney(seat.getMoney());
            }else{
                yanchuOrderDetail.setMoney(yanchuSeat.getMoney());
            }

            yanchuOrderDetail.setTicket(yanchuSeat.getTicket());
            yanchuOrderDetail.setShowNumber(yanchuSeat.getShowNumber());
            yanchuOrderDetail.setUserId(yanchuOrder.getUserId());
            yanchuOrderDetail.setPerformId(yanchuOrder.getPerformId());
            yanchuOrderDetail.setTicketType(yanchuOrder.getTicketType());
            yanchuOrderDetail.setTicketWay(yanchuOrder.getTicketWay());
            yanchuOrderDetail.setBuyerPhone(seat.getBuyerPhone());
            if(null != seat.getUserinfoId()){
                yanchuOrderDetail.setUserinfoId(seat.getUserinfoId());
                if(yanchuOrder.getTicketType().equals(PerformConstants.TICKET_TYPE_WECHAT)){
                    userInfo = yanchuUserInfoMapper.selectYanchuUserInfoById(seat.getUserinfoId());
                    if(null == userInfo){
                        throw new ServiceException("观影人不存在！");
                    }

                    yanchuOrderDetail.setUserinfoUserName(userInfo.getUserName());
                    yanchuOrderDetail.setUserinfoIdType(userInfo.getIdType());
                    yanchuOrderDetail.setUserinfoIdNumber(userInfo.getIdNumber());
                }else{
                    yanchuOrderDetail.setUserinfoUserName(seat.getUserinfoUserName());
                    yanchuOrderDetail.setUserinfoIdType(seat.getUserinfoIdType());
                    yanchuOrderDetail.setUserinfoIdNumber(seat.getUserinfoIdNumber());
                }
            }else{
                yanchuOrderDetail.setUserinfoIdNumber(seat.getIdNum());
                if(StringUtils.isNotEmpty(seat.getIdType())){
                    yanchuOrderDetail.setUserinfoIdType(Integer.valueOf(seat.getIdType()));
                }
                yanchuOrderDetail.setUserinfoUserName(seat.getUserName());
            }
            yanchuOrderDetail.setPriceId(yanchuSeat.getPriceId());
            yanchuTicketPrice = priceMap.get(seat.getPriceId());
            if(null == yanchuTicketPrice){
                throw new ServiceException("价格不正确！");
            }
            yanchuOrderDetail.setTicketTitle(yanchuTicketPrice.getTitle());
            yanchuOrderDetail.setExpireTime(expireTime);
            if(PerformConstants.COMB_AREAS.contains(Long.valueOf(seat.getAreaId()))){
                yanchuOrderDetail.setIsComb(1);
            }
            if(null != seat.getYingfuMoney()){
                yanchuOrderDetail.setYingfuMoney(seat.getYingfuMoney());
            }else{
                yanchuOrderDetail.setYingfuMoney(yanchuSeat.getMoney());
            }
            if(null!=seat.getJianmianMoney()){
                yanchuOrderDetail.setJianmianMoney(seat.getJianmianMoney());
            }

            details.add(yanchuOrderDetail);
        }
        int count = yanchuOrderDetailMapper.insertBatchDetail(details);
        return count;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public YanchuOrder notifyOrder(String outTradeNo, BigDecimal totalFee, String transactionId,YanchuOrder yanchuOrder) {
        logger.info("notifyOrder orderVo:{} totalFee:{} tradeNo:{}", outTradeNo, totalFee, transactionId);
        if(null == yanchuOrder){
            yanchuOrder = yanchuOrderMapper.selectYanchuOrderByNo(outTradeNo);
            if (null == yanchuOrder) {
                return null;
            }
        }
        Integer initStatus = PerformConstants.ORDER_WAIT_PAY;
        Integer toStatus = PerformConstants.ORDER_PAY;
        if (yanchuOrder.getStatus() == PerformConstants.ORDER_PAY) {
            logger.warn("存在重复支付回调 orderNo:{} tradeNo：{}", outTradeNo, transactionId);
            return null;
        }
        if (yanchuOrder.getStatus() == PerformConstants.ORDER_CANCEL) {
            initStatus = PerformConstants.ORDER_CANCEL;
            toStatus = PerformConstants.ORDER_WAIT_REFUND;
        }
        yanchuOrder.setStatus(toStatus);
        yanchuOrder.setUpdateTime(new Date());
        //更新订单表
        int count = yanchuOrderMapper.updateOrderPayStatus(outTradeNo,transactionId, toStatus,initStatus);
        if (count == 0) {
            logger.warn("更新支付失败 orderNo:{} tradeNo：{}", outTradeNo, transactionId);
            return null;
        } else if (toStatus == PerformConstants.ORDER_WAIT_REFUND) {
            logger.warn("更新支付等待退款 orderNo:{} tradeNo：{}", outTradeNo, transactionId);
            return null;
        }
        //更新订单详情表
        int detailCount = yanchuOrderDetailMapper.updateOrderDetailByNo(yanchuOrder.getId(), PerformConstants.ORDER_PAY,
                PerformConstants.ORDER_WAIT_PAY);
        if (detailCount > 0) {
            //更新座位表
            int seatCount = yanchuSeatMapper.updateSeatByOrderId(yanchuOrder.getId(),PerformConstants.TICKET_SEAT_PAY,
                    PerformConstants.TICKET_SEAT_WAIT_PAY);
            if (detailCount != detailCount) {
                logger.warn("更新座位失败 outTradeNo:{} seatCount：{} detailCount:{}", outTradeNo, seatCount, detailCount);
                throw new ServiceException("更新座位失败！");
            }else{
                YanchuSeat yanchuSeat = new YanchuSeat();
                yanchuSeat.setOrderId(yanchuOrder.getId());
                List<YanchuSeat> seatList = yanchuSeatMapper.selectYanchuSeatList(yanchuSeat);
                iYanchuSeatService.refreshTicketList(seatList,yanchuOrder.getSessionId());
            }
        }
        //更新票房、积分
        iYanchuScoreService.updateNumsMoney(detailCount, yanchuOrder.getTotalMoney(), yanchuOrder.getSessionId(),
                yanchuOrder.getUserId(), yanchuOrder.getTotalMoney().intValue(),yanchuOrder.getPerformId(),yanchuOrder);
        return yanchuOrder;
    }

    /**
     * 修改订单
     *
     * @param yanchuOrder 订单
     * @return 结果
     */
    @Override
    public int updateYanchuOrder(YanchuOrder yanchuOrder) {
        yanchuOrder.setUpdateTime(DateUtils.getNowDate());
        return yanchuOrderMapper.updateYanchuOrder(yanchuOrder);
    }

    @Override
    public int payYanchuOrder(OrderPayParamVo orderPayParamVo){
        YanchuOrder order = this.selectOrderById(orderPayParamVo.getOrderId());
        if(null == order){
            throw new ServiceException("订单编码不正确");
        }

        order.setTicketStatus(orderPayParamVo.getTicketStatus());
        order.setPayWay(orderPayParamVo.getPayWay());
        order.setTicketDemo(orderPayParamVo.getDemo());
        order.setPayDemo(orderPayParamVo.getPayDemo());
        order.setPayName(orderPayParamVo.getPayName());
        return yanchuOrderMapper.updateYanchuOrderPay(order);
    }

    @Override
    public void closeExpireOrder() {
        logger.info("closeExpireOrder");
        List<YanchuOrder> list = yanchuOrderMapper.selectExpireOrderList();
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        for (YanchuOrder order : list) {
            releaseOrder(order);
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int releaseOrder(YanchuOrder yanchuOrder) {
        logger.info("releaseOrder:{} orderNo:{}",yanchuOrder.getId(),yanchuOrder.getOrderId());
        //更新座位状态
        int count = yanchuSeatMapper.updateSeatCancel(yanchuOrder.getId(), PerformConstants.TICKET_SEAT_OPEN, PerformConstants.TICKET_SEAT_WAIT_PAY);

        //更新订单状态
        yanchuOrderMapper.updateExpireOrder(yanchuOrder.getId(), PerformConstants.ORDER_CANCEL, PerformConstants.ORDER_WAIT_PAY);
        yanchuOrderDetailMapper.updateOrderDetailByNo(yanchuOrder.getId(), PerformConstants.ORDER_CANCEL,
                PerformConstants.ORDER_WAIT_PAY);
        //退还储值卡
        if(null != yanchuOrder.getBalanceAmt() && yanchuOrder.getBalanceAmt().compareTo(BigDecimal.ZERO) > 0){
            yanchuStorageCradService.refund(yanchuOrder,null);
        }
        //退还观演卡
        if(null != yanchuOrder.getCardAmt() && yanchuOrder.getCardAmt().compareTo(BigDecimal.ZERO) > 0){
            YanchuConsumeRecord consumeRecord = new YanchuConsumeRecord();
            consumeRecord.setOrderId(yanchuOrder.getId());
            consumeRecord.setBindId(yanchuOrder.getUserId());
            consumeRecord.setCardType(PerformConstants.CARD_TYPE_CARD);
            consumeRecord.setConType(PerformConstants.CONSUME_TYPE_CARD);
            List<YanchuConsumeRecord> list = yanchuConsumeRecordMapper.selectYanchuConsumeRecordList(consumeRecord);
            if(CollectionUtils.isNotEmpty(list)){
                for(YanchuConsumeRecord record:list){
                    if(record.getAmount().compareTo(BigDecimal.ZERO)>0){
                        continue;
                    }
                    yanchuMovieCardService.refundByRecord(record,null);
                }
            }
        }
        cancelOrderCache(yanchuOrder.getId());
        return count;
    }

    /**
     * 修改座位缓存
     * @param orderId
     */
    public void cancelOrderCache(Long orderId) {
        logger.info("cancelOrderCache:{}",orderId);
        YanchuSeat yanchuSeat = new YanchuSeat();
        yanchuSeat.setOrderId(orderId);
        List<YanchuSeat> seatList = yanchuSeatMapper.selectYanchuSeatList(yanchuSeat);
        if (CollectionUtils.isNotEmpty(seatList)) {
            Map<String, YanchuSeat> map = Maps.newHashMap();
            String keySession = CacheConstants.TICKET_LOCK_KEY + seatList.get(0).getSessionId();
            String hKey = null;
            for (YanchuSeat seatVo : seatList) {
                hKey = seatVo.getAreaId() + "-" + seatVo.getRowNumber() + "-" + seatVo.getxPos();
                map.put(hKey, seatVo);
            }
            logger.debug("cancelOrderCache orderId:{} map:{}",keySession,map);
            redisCache.mMapSet(keySession, map, 180, TimeUnit.DAYS);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cancelOrder(Long orderId) {
        YanchuOrder order = yanchuOrderMapper.selectYanchuOrderById(orderId);
        if(null == orderId){
            return 1;
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(!order.getUserId().equals(loginUser.getUser().getUserId())){
            logger.info("cancelOrder error:{} {}",order.getUserId(),loginUser.getUser().getUserId());
            throw new ServiceException("取消失败！");
        }
        int count = releaseOrder(order);
        return count;
    }

    /**
     * 批量删除订单
     *
     * @param ids 需要删除的订单主键
     * @return 结果
     */
    @Override
    public int deleteYanchuOrderByIds(Long[] ids) {
        return yanchuOrderMapper.deleteYanchuOrderByIds(ids);
    }

    /**
     * 删除订单信息
     *
     * @param id 订单主键
     * @return 结果
     */
    @Override
    public int deleteYanchuOrderById(Long id) {
        YanchuOrder order = yanchuOrderMapper.selectYanchuOrderById(id);
        if(null == order){
            return 1;
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(!loginUser.getUser().getUserId().equals(order.getUserId())){
            throw new ServiceException("删除失败！");
        }
        return yanchuOrderMapper.deleteYanchuOrderById(id);
    }

    /**
     * (管控台)查询订单列表
     *
     * @return 订单集合
     */
    @Override
    public List<OrderVo> selectYanchuOrderPageList(Long deptId, Long performId, Long sessionId,
                                                   Integer orderStatus, String orderId, String ticketBuyer,
                                                   String phone) {
        List<OrderVo> orderVoList = yanchuOrderMapper.selectYanchuOrderPageList(deptId, performId, sessionId,
                orderStatus, orderId, ticketBuyer, phone);
        if (!CollectionUtils.isEmpty(orderVoList)) {
            for (OrderVo orderVo : orderVoList) {
                orderVo.getSessionVo().setWeek(DateUtils.dateToWeek(orderVo.getSessionVo().getSessionDate()));
            }
        }
        return orderVoList;
    }

    /**
     * 场次是否全部退款
     *
     * @param sessionId
     * @return
     */
    @Override
    public Boolean checkOrderStatus(Long sessionId) {
        YanchuSession yanchuSession = yanchuSessionMapper.selectYanchuSessionById(sessionId);
        if (Const.THREE.equals(yanchuSession.getStatus())) {
            return yanchuOrderMapper.checkOrderStatus(sessionId) > 0;
        }
        return false;
    }

    @Override
    public OrderStatisticsVO getOrderStatisticsVO(QueryOrderListVO queryOrderListVO) {
        List<BigDecimal> orderStatistics = null;
        if(queryOrderListVO.getTicketType().equals(PerformConstants.TICKET_TYPE_BACKEND)){
            orderStatistics = yanchuOrderMapper.getBackendOrderStatistics(queryOrderListVO);
        }else{
            queryOrderListVO.setTicketType(1);
            orderStatistics = yanchuOrderMapper.getOrderStatistics(queryOrderListVO);
        }
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        if(CollectionUtils.isNotEmpty(orderStatistics)){
            Field[] declaredFields = OrderStatisticsVO.class.getDeclaredFields();
            for(int i = 0;i<declaredFields.length;i++) {
                if(orderStatistics.size()<=i){
                    continue;
                }
                System.out.println(declaredFields[i].getName());
                //反射时让私有变量变成可访问
                declaredFields[i].setAccessible(true);
                try {
                    if(i==0||i==1||i==6){
                        BigDecimal bigDecimal = orderStatistics.get(i);
                        declaredFields[i].set(orderStatisticsVO,bigDecimal.intValue());
                    }else {
                        declaredFields[i].set(orderStatisticsVO,orderStatistics.get(i));
                    }
                } catch (Exception e) {
                    logger.error("统计数据处理失败！",e);
                }
            }
        }
        orderStatisticsVO.setShouldPaySum(orderStatisticsVO.getOriginSum().subtract(orderStatisticsVO.getReduceSum()));
        orderStatisticsVO.setShouldSellSum(orderStatisticsVO.getActualPaySum().subtract(orderStatisticsVO.getRefundPriceSum()));
        orderStatisticsVO.setTitle(queryOrderListVO.getExportMsg());
        if(null!=queryOrderListVO.getStatus()&&queryOrderListVO.getStatus()==1){
            orderStatisticsVO.setActualPaySum(new BigDecimal(0));
            orderStatisticsVO.setWechatPaySum(new BigDecimal(0));
            orderStatisticsVO.setCardPaySum(new BigDecimal(0));
            orderStatisticsVO.setBalancePaySum(new BigDecimal(0));
            orderStatisticsVO.setShouldSellSum(new BigDecimal(0));
        }
        return orderStatisticsVO;
    }


    @Override
    public void exportOrderStatistics(HttpServletResponse response, QueryOrderListVO query) {
        OrderStatisticsVO orderStatisticsVO = getOrderStatisticsVO(query);
        String title = orderStatisticsVO.getTitle();
        String[] split = title.split("/n");
        StringBuilder builder = new StringBuilder();
        for (String s : split) {
            builder.append(s).append("\n");
        }
        orderStatisticsVO.setTitle(builder.toString());
        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
        String templateFileName = tempUrl + "orderstaticTemp.xlsx";
        if(null != query.getTicketType() && query.getTicketType().equals(PerformConstants.TICKET_TYPE_BACKEND)){
            templateFileName = tempUrl + "backendOrderstaticTemp.xlsx";
        }
        String fileName = "orderStatisticsData"+System.currentTimeMillis()+".xlsx";
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
            EasyExcel.write(response.getOutputStream()).withTemplate(templateFileName).sheet().doFill(orderStatisticsVO);
        } catch (Exception e) {
            logger.error("exportOrderStatistics error",e);
            throw new RuntimeException(e);
        }

    }


    @Override
    public void exportOrderList(HttpServletResponse response, QueryOrderListVO query) {
        List<ExportOrderListVO> list = new ArrayList<>();
        orderListDataProcessing(this.selectOrderList(query),list);
        executeExportOrder(list,response,query);
    }

    @Override
    public Integer getExportCount(QueryOrderListVO query) {
        return this.selectOrderList(query).size();
    }

    //处理数据
    public void orderListDataProcessing(List<YanchuOrderVO> orderVOList,List<ExportOrderListVO> exportOrderListVOS){
        //查出所有订单id下的子订单然后塞入
        List<Long> collect = orderVOList.stream().map(YanchuOrderVO::getId).collect(Collectors.toList());
        List<ExcelOrderDetailVo> excelOrderDetailVO = yanchuOrderDetailMapper.getExcelOrderDetailVO(collect);
        Map<Long, List<ExcelOrderDetailVo>> collect1 = excelOrderDetailVO.stream().collect(Collectors.groupingBy(ExcelOrderDetailVo::getOrderId));
        final String[] idTypeName = {""};
        final String[] ticketStatusName = {"无"};
        orderVOList.forEach(yanchuOrderVO -> {
            collect1.forEach((k,v)->{
                if(k.equals(yanchuOrderVO.getId())){
                    yanchuOrderVO.setExcelOrderDetailVoList(v);
                }
            });
            if(CollectionUtils.isEmpty(yanchuOrderVO.getExcelOrderDetailVoList())){
                return;
            }
            yanchuOrderVO.getExcelOrderDetailVoList().forEach(details->{
                ExportOrderListVO exportOrderListVO = new ExportOrderListVO();
                exportOrderListVO.setOrderNum(yanchuOrderVO.getOrderId());
                exportOrderListVO.setOrderTime(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",yanchuOrderVO.getCreateTime()));
                exportOrderListVO.setSxjy(yanchuOrderVO.getOpera());
                exportOrderListVO.setShouName(yanchuOrderVO.getPerformName());
                exportOrderListVO.setPerformanceCount(yanchuOrderVO.getSessionName());
                exportOrderListVO.setTicketCount(yanchuOrderVO.getExcelOrderDetailVoList().size()+"");
                if(StringUtils.isNotEmpty(yanchuOrderVO.getDiscountTypeName())){
                    exportOrderListVO.setYhzc(yanchuOrderVO.getDiscountTypeName());//优惠政策
                }else{
                    exportOrderListVO.setYhzc("无");
                }
                if(null != yanchuOrderVO.getYingfuMoney()){
                    exportOrderListVO.setPrice(yanchuOrderVO.getYingfuMoney().toString());//原价
                }else{
                    exportOrderListVO.setPrice("0");//原价
                }

                if(null!=yanchuOrderVO.getDiscountAmt()){
                    exportOrderListVO.setOrderRelief(yanchuOrderVO.getDiscountAmt().toString());//减免
                    exportOrderListVO.setOrderShouldPay(yanchuOrderVO.getYingfuMoney().subtract(yanchuOrderVO.getDiscountAmt()).toString());//应付
                }else{
                    exportOrderListVO.setOrderRelief("0.00");//减免
                    exportOrderListVO.setOrderShouldPay(yanchuOrderVO.getYingfuMoney().toString());//应付
                }

                if(yanchuOrderVO.getTicketType().equals(PerformConstants.TICKET_TYPE_WECHAT) ||
                        (null!=yanchuOrderVO.getTicketStatus() && yanchuOrderVO.getTicketStatus().equals(PerformConstants.TICKET_PAY))){
                    exportOrderListVO.setOrderActualPay(yanchuOrderVO.getPrice().get("totalMoney").toString());//实付
                }else{
                    exportOrderListVO.setOrderActualPay("0.00");
                }
                if(yanchuOrderVO.getTicketType().equals(PerformConstants.TICKET_TYPE_WECHAT)){
                    exportOrderListVO.setRefund(yanchuOrderVO.getWechatRefundAmt().add(yanchuOrderVO.getBalanceRefundAmt()).add(yanchuOrderVO.getCardRefundAmt()).toString());
                }else if(null != yanchuOrderVO.getRefundMoney()){
                    exportOrderListVO.setRefund(yanchuOrderVO.getRefundMoney().toString());
                }else{
                    exportOrderListVO.setRefund("0.00");
                }

                exportOrderListVO.setOrderChannel("微信小程序");
                StringBuilder str = getStringBuilder(yanchuOrderVO);
                exportOrderListVO.setPayType(str.toString());
                exportOrderListVO.setPayNumber(yanchuOrderVO.getPrePayId());
                exportOrderListVO.setTicketPickType("电子票");
                exportOrderListVO.setOrderType("普通订单");

                exportOrderListVO.setOrderStatus(Objects.requireNonNull(OrderStatusEnum.indexOf(yanchuOrderVO.getStatus())).getValue());
                exportOrderListVO.setBuyPeople(yanchuOrderVO.getContacts());
                exportOrderListVO.setBuyPhoneNumber(yanchuOrderVO.getContactNumber());
                exportOrderListVO.setContactName(yanchuOrderVO.getOcontacts());
                exportOrderListVO.setContactPhoneNumber(yanchuOrderVO.getOcontactNumber());
                exportOrderListVO.setTicketStalls(details.getPriceName());
                if(null != details.getYingfuMoney()){
                    exportOrderListVO.setPricing(details.getYingfuMoney().toString());
                }else{
                    exportOrderListVO.setPricing(yanchuOrderVO.getPrice().get("totalMoney").toString());
                }

                exportOrderListVO.setSeat(details.getAreaName()+details.getShowNumber());
                exportOrderListVO.setTicketPeopleName(details.getUserinfoUserName());
                if(null == yanchuOrderVO.getTicketStatus()){
                    ticketStatusName[0] ="无";
                }else if(yanchuOrderVO.getTicketStatus().equals(2)){
                    ticketStatusName[0] ="欠款";
                }else if(yanchuOrderVO.getTicketStatus().equals(1)){
                    ticketStatusName[0] ="已付款";
                }
                exportOrderListVO.setTicketPayStatus(ticketStatusName[0]);
                if(null != details.getUserinfoIdType()){
                    if(details.getUserinfoIdType().equals(PerformConstants.ID_TYPE_3)){
                        idTypeName[0] ="港澳台通行证及居住证";
                    }else if(details.getUserinfoIdType().equals(PerformConstants.ID_TYPE_2)){
                        idTypeName[0] ="护照";
                    }else{
                        idTypeName[0] ="身份证";
                    }
                }else{
                    idTypeName[0] ="无";
                }
                exportOrderListVO.setIdType(idTypeName[0]);
                exportOrderListVO.setIdNumber(details.getUserinfoIdNumber());
                exportOrderListVO.setTicketStatus(Objects.requireNonNull(TicketStatusEnum.indexOf(details.getStatus())).getValue());
                if(null != details.getJianmianMoney()){
                    exportOrderListVO.setYouhuiRelief(details.getJianmianMoney().toPlainString());//减免
                }else{
                    exportOrderListVO.setYouhuiRelief("0.00");
                }

                exportOrderListVO.setYouhuihouPrice(details.getMoney().toString());//优惠后金额
                if(yanchuOrderVO.getTicketType().equals(PerformConstants.TICKET_TYPE_WECHAT) ||
                        (null!=yanchuOrderVO.getTicketStatus() && yanchuOrderVO.getTicketStatus().equals(PerformConstants.TICKET_PAY))){
                    exportOrderListVO.setTicketActualPay(details.getMoney().toString());//实付
                }else{
                    exportOrderListVO.setTicketActualPay("0.00");//实付
                }
                exportOrderListVO.setUserName(yanchuOrderVO.getUserName());
                exportOrderListVO.setTicketWayName(yanchuOrderVO.getTicketWayName());
                exportOrderListVOS.add(exportOrderListVO);
            });
        });
    }

    private static StringBuilder getStringBuilder(YanchuOrderVO yanchuOrderVO) {
        StringBuilder str = new StringBuilder();
        if(yanchuOrderVO.getTicketType().equals(PerformConstants.TICKET_TYPE_BACKEND)){
            if(null != yanchuOrderVO.getPayWay()){
                if(yanchuOrderVO.getPayWay().equals(PerformConstants.PAYWAY_1)){
                    str.append("对公转账");
                }else if(yanchuOrderVO.getPayWay().equals(PerformConstants.PAYWAY_2)){
                    str.append("抖音支付");
                }else if(yanchuOrderVO.getPayWay().equals(PerformConstants.PAYWAY_3)){
                    str.append("微信支付");
                }else if(yanchuOrderVO.getPayWay().equals(PerformConstants.PAYWAY_4)){
                    str.append("现金");
                }else if(yanchuOrderVO.getPayWay().equals(PerformConstants.PAYWAY_5)){
                    str.append(yanchuOrderVO.getPayName());
                }
            }else{
                str.append("无");
            }
        }else{
            if(yanchuOrderVO.getBalanceAmt()!=null&&new BigDecimal(yanchuOrderVO.getBalanceAmt()).doubleValue()>0){
                str.append("余额支付+");
            }
            if(yanchuOrderVO.getCardAmt()!=null&&new BigDecimal(yanchuOrderVO.getCardAmt()).doubleValue()>0){
                str.append("观演卡支付+");
            }
            if(yanchuOrderVO.getWechatAmt()!=null&&new BigDecimal(yanchuOrderVO.getWechatAmt()).doubleValue()>0){
                str.append("微信支付+");
            }
            if(str.length()>1){
                str.deleteCharAt(str.length() - 1);
            }
        }
        return str;
    }

    /**
     * 导出订单列表  执行
     */
    public void executeExportOrder(List<ExportOrderListVO> list,HttpServletResponse response,QueryOrderListVO query){
        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
        String templateFileName = tempUrl + "orderListExportTemp.xlsx";
        Integer mergeCount = 22;
        if(query.getTicketType().equals(PerformConstants.TICKET_TYPE_BACKEND)){
            templateFileName = tempUrl+"backendOrderListExportTemp.xlsx";
            mergeCount = 19;
        }
        String fileName = "orderList"+System.currentTimeMillis()+".xlsx";

//        String fileName = "C:/Users/lovepig/Desktop/" + "导出订单列表" + System.currentTimeMillis() + ".xlsx";
        try {
            //替换成自己的数据
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
            ExcelWriterBuilder write = EasyExcel.write(response.getOutputStream());
            for(int i = 0;i < mergeCount;i++){
                write.registerWriteHandler(new CustomMergeStrategy(list.stream().map(ExportOrderListVO::getOrderNum).collect(Collectors.toList()), i));
            }
            //只有一个直接写 >1的合并 分开写入
            try (ExcelWriter excelWriter = write.withTemplate(templateFileName).build()){
                WriteSheet writeSheet = EasyExcel.writerSheet().build();
                // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
                // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
                // 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
                // 如果数据量大 list不是最后一行 参照下一个
                FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
                excelWriter.fill(list, fillConfig, writeSheet);
                Map<String, Object> map = MapUtils.newHashMap();
                String[] split = query.getExportMsg().split("/n");
                StringBuilder builder = new StringBuilder();
                for (String s : split) {
                    builder.append(s).append("\n");
                }
                map.put("title", builder.toString());
                excelWriter.fill(map, writeSheet);
            }
        } catch (Exception e) {
            logger.error("executeExportOrder",e);
        }
    }


    /**
     * 最简单的填充
     *
     * @since 2.1.1
     */

    public void export(QueryOrderListVO queryOrderListVO) {
        OrderStatisticsVO orderStatisticsVO = getOrderStatisticsVO(queryOrderListVO);
        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
        String templateFileName = "C:/Users/lovepig/Desktop/" + "orderstaticTemp.xlsx";

        // 方案1 根据对象填充
        String fileName = "C:/Users/lovepig/Desktop/" + "simpleFill" + System.currentTimeMillis() + ".xlsx";
        // 这里 会填充到第一个sheet， 然后文件流会自动关闭
        EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(orderStatisticsVO);

        // 方案2 根据Map填充
//        String fileName = "C:/Users/lovepig/Desktop/" + "simpleFill" + System.currentTimeMillis() + ".xlsx";
//        // 这里 会填充到第一个sheet， 然后文件流会自动关闭
//        Map<String, Object> map = MapUtils.newHashMap();
//        map.put("title", "张三\n李四");
//        map.put("orderSum", 5.2);
//        EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(map);
    }


}
